package com.xbongbong.pro.aiassistant.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.aiassistant.handle.SaasAiAssistantStrategyHandle;
import com.xbongbong.pro.aiassistant.service.SsHistoryService;
import com.xbongbong.pro.domain.entity.AiAssistantEntity;
import com.xbongbong.pro.domain.entity.AiAssistantHistoryEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.history.pojo.AiAssistantHistoryPojo;
import com.xbongbong.pro.smartsettings.pojo.SsHistoryValidPojo;
import com.xbongbong.pro.smartsettings.pojo.dto.SmartStrategyRabbitMqDTO;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.AiAssistantHistoryModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @description: 智能助手--数据记录
 * @Author: hongxiao
 * @date: 2019-05-09 20:31
 * @since v1.0
 */
@Service("ssHistoryService")
public class SsHistoryServiceImpl implements SsHistoryService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SsHistoryServiceImpl.class);

    @Resource
    private AiAssistantHistoryModel aiAssistantHistoryModel;
    @Resource
    private SaasAiAssistantStrategyHandle saasAiAssistantStrategyHandle;

    @Override
    public List<SsHistoryValidPojo> getValidHistoryList(SmartStrategyRabbitMqDTO rabbitMqDTO, Map<Long, List<Long>> dataIdsMap,
                                    Map<Long, List<Long>> waitInvalidIdsMap, Map<Long, List<AiAssistantHistoryEntity>> waitInvalidListMap,
                                                        Map<Long, List<AiAssistantHistoryEntity>> workReportValidListMap) {

        // 获取策略对应的执行动作
        List<AiAssistantEntity> smartList = rabbitMqDTO.getList();
        Map<Long, Integer> smartActionMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, AiAssistantEntity> smartMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        smartList.forEach(item -> {
            smartActionMap.put(item.getId(), item.getAction());
            smartMap.put(item.getId(), item);
        });

        List<SsHistoryValidPojo> validPojoList = new ArrayList<>();
        // 获取记录数据
        Map<Long, List<AiAssistantHistoryEntity>> historyList = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        getValidHistoryList(rabbitMqDTO, historyList, workReportValidListMap);
        // TODO 自定义执行策略：每多周/多月一个周期需要特殊处理数据是否是本周期内的数据，查询数据量大，目前先不开放

        // 触发条件数据及历史记录无时，直接返回
        if(historyList.isEmpty() && dataIdsMap.isEmpty()) {
            return new ArrayList<>();
        }

        if (historyList.isEmpty()) {
            // 只有添加
            validPojoList.addAll(addValidList(dataIdsMap, smartMap));
        } else {
            // 新添加的数据
            Map<Long, List<Long>> addListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 与记录交集的数据
            Map<Long, List<Long>> retainListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if(!dataIdsMap.isEmpty()) {
                dataIdsMap.forEach((smartId, dataIds) -> {
                    if(historyList.containsKey(smartId)) {
                        retainListMap.put(smartId, dataIds);
                    } else {
                        addListMap.put(smartId, dataIds);
                    }
                });
            }
            // 新添加的数据
            validPojoList.addAll(addValidList(addListMap, smartMap));


            // 交集(添加/更新/失效/待失效）
            historyList.forEach((smartId, valueList) -> {

                List<Long> dataIds = retainListMap.get(smartId);
                if(Objects.isNull(dataIds)) {
                    dataIds = new ArrayList<>();
                }

                // 交集数据
                List<Long> retainDataIds = new ArrayList<>();
                // 交集的记录
                if(!dataIds.isEmpty()) {
                    // 交集数据
                    // 新添加记录数据
                    for (AiAssistantHistoryEntity history : valueList) {
                        if(dataIds.contains(history.getDataId())) {
                            retainDataIds.add(history.getDataId());
                        }
                    }
                    // 数据id差集（添加）
                    dataIds.removeAll(retainDataIds);
                }


                // 更新的记录
                List<AiAssistantHistoryEntity> updateList = new ArrayList<>();
                List<Long> updateIds = new ArrayList<>();
                // 失效的记录
                List<Long> invalidIdsList = new ArrayList<>();
                // 待失效的记录
                List<AiAssistantHistoryEntity> waitInvalidList = new ArrayList<>();
                List<Long> waitInvalidIds = new ArrayList<>();

                // 执行动作
                Integer action = smartActionMap.get(smartId);
                // 记录是否失效
                for (AiAssistantHistoryEntity history : valueList) {
                    // 执行动作未改变
                    if(Objects.equals(history.getAction(), action)) {
                        // 工作报告，全部更新
                        if(Objects.equals(XbbRefTypeEnum.WORK_REPORT.getCode(), history.getBusinessType())) {
                            updateIds.add(history.getDataId());
                            updateList.add(history);
                        } else if(retainDataIds.contains(history.getDataId())) {
                            // 更新的记录
                            Long aiAssistantId = history.getAiAssistantId();
                            if (smartMap.containsKey(aiAssistantId)) {
                                AiAssistantEntity aiAssistantEntity = smartMap.get(aiAssistantId);
                                JSONObject strategy = aiAssistantEntity.getStrategy();
                                Integer strategyNum = strategy.getInteger("strategyNum") == null ? 0 : strategy.getInteger("strategyNum");
                                if (history.getTriggerNum() >= strategyNum) {
                                    // 智能助手执行次数大于等于记录次数时，不在执行
                                    continue;
                                }
                            }
                            updateList.add(history);
                            updateIds.add(history.getDataId());
                        } else {
                            // 待处理的数据
                            waitInvalidList.add(history);
                            waitInvalidIds.add(history.getDataId());
                        }
                    } else {
                        // 执行动作改变：记录失效
                        invalidIdsList.add(history.getId());
                    }

                }

                // 添加数据
                AiAssistantEntity entity = smartMap.get(smartId);
                List<AiAssistantHistoryEntity> addList = getAddHistoryList(dataIds, entity);

                // 需要添加和更新的数据ids
                List<Long> addAndUpdateIds = new ArrayList<>(dataIds);
                addAndUpdateIds.addAll(updateIds);

                // 生成pojo
                SsHistoryValidPojo pojo = new SsHistoryValidPojo();
                pojo.setSmartSettingsId(smartId);
                pojo.setAddList(addList);
                pojo.setUpdateList(updateList);
                pojo.setInvalidIdsList(invalidIdsList);
                pojo.setAddAndUpdateIds(addAndUpdateIds);
                pojo.setWaitInvalidList(waitInvalidList);
                pojo.setWaitInvalidIds(waitInvalidIds);
                validPojoList.add(pojo);

                if(!waitInvalidIds.isEmpty()) {
                    waitInvalidIdsMap.put(smartId, waitInvalidIds);
                    waitInvalidListMap.put(smartId, waitInvalidList);
                }
            });
        }

        return validPojoList;
    }


    @Override
    public AiAssistantHistoryPojo getTriggerNum(SmartStrategyRabbitMqDTO rabbitMqDTO, Map<Long, List<Long>> dataIdsMap){
        AiAssistantHistoryPojo aiAssistantHistoryPojo = new AiAssistantHistoryPojo();
        try {
            String corpid = rabbitMqDTO.getCorpid();
            Map<Long, List<AiAssistantHistoryEntity>> triggerNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, List<AiAssistantHistoryEntity>> workReportTriggerNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionsUtil.isEmpty(rabbitMqDTO.getList())) {
                return aiAssistantHistoryPojo;
            }
            // 获取智能助手的执行次数
            rabbitMqDTO.getList().forEach(item -> {
                Long aiAssistantId = item.getId();
                if (dataIdsMap.containsKey(aiAssistantId)) {
                    List<Long> dataIdList = dataIdsMap.get(aiAssistantId);
                    List<AiAssistantHistoryEntity> list = saasAiAssistantStrategyHandle.getHistoryList(dataIdList, corpid, aiAssistantId );
                    if (CollectionsUtil.isNotEmpty(list)) {
                        if (Objects.equals(SaasMarkEnum.SAAS.getCode(), item.getSaasMark())
                                && Objects.equals(XbbRefTypeEnum.WORK_REPORT.getCode(), item.getBusinessType())) {
                            // 工作报告
                            workReportTriggerNumMap.put(aiAssistantId, list);
                        } else {
                            triggerNumMap.put(aiAssistantId, list);
                        }
                    }
                }

            });
            // 触发条件数据及历史记录无时，直接返回
            if(triggerNumMap.isEmpty() && dataIdsMap.isEmpty()) {
                return aiAssistantHistoryPojo;
            }
            aiAssistantHistoryPojo.setTriggerNumMap(triggerNumMap);
            aiAssistantHistoryPojo.setWorkReportTriggerNumMap(workReportTriggerNumMap);
            Map<Long, List<Long>> waitInvalidIdsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, List<AiAssistantHistoryEntity>> waitInvalidListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Integer> smartActionMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, AiAssistantEntity> smartMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            rabbitMqDTO.getList().forEach(item -> {
                smartActionMap.put(item.getId(), item.getAction());
                smartMap.put(item.getId(), item);
            });
            List<SsHistoryValidPojo> validPojoList;
            if (triggerNumMap.isEmpty()) {
                // 只有添加
                validPojoList = addValidList(dataIdsMap, smartMap);
            } else {
                // 新添加的数据
                Map<Long, List<Long>> addListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                // 与记录交集的数据
                Map<Long, List<Long>> retainListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if(!dataIdsMap.isEmpty()) {
                    dataIdsMap.forEach((smartId, dataIds) -> {
                        if(triggerNumMap.containsKey(smartId)) {
                            retainListMap.put(smartId, dataIds);
                        } else {
                            addListMap.put(smartId, dataIds);
                        }
                    });
                }
                // 新添加的数据
                validPojoList = addValidList(addListMap, smartMap);


                // 交集(添加/更新/失效/待失效）
                for (Map.Entry<Long, List<AiAssistantHistoryEntity>> entry : triggerNumMap.entrySet()) {
                    Long smartId = entry.getKey();
                    List<AiAssistantHistoryEntity> list = entry.getValue();
                    List<Long> dataIds = retainListMap.get(smartId);
                    if (Objects.isNull(dataIds)) {
                        dataIds = new ArrayList<>();
                    }

                    // 交集数据
                    List<Long> retainDataIds = new ArrayList<>();
                    // 交集的记录
                    if (!dataIds.isEmpty()) {
                        // 交集数据
                        // 新添加记录数据
                        for (AiAssistantHistoryEntity aiAssistantHistoryEntity : list) {
                            Long dataId = aiAssistantHistoryEntity.getDataId();
                            if (dataIds.contains(dataId)) {
                                retainDataIds.add(dataId);
                            }
                        }
                        // 数据id差集（添加）
                        dataIds.removeAll(retainDataIds);
                    }
                    // 更新的记录
                    List<AiAssistantHistoryEntity> updateList = new ArrayList<>();
                    List<Long> updateIds = new ArrayList<>();
                    // 失效的记录
                    List<Long> invalidIdsList = new ArrayList<>();
                    // 待失效的记录
                    List<AiAssistantHistoryEntity> waitInvalidList = new ArrayList<>();
                    List<Long> waitInvalidIds = new ArrayList<>();

                    // 执行动作
                    Integer action = smartActionMap.get(smartId);
                    // 记录是否失效
                    for (AiAssistantHistoryEntity history : list) {
                        // 执行动作未改变
                        if (Objects.equals(history.getAction(), action)) {
                            // 工作报告，全部更新
                            if (Objects.equals(XbbRefTypeEnum.WORK_REPORT.getCode(), history.getBusinessType())) {
                                updateIds.add(history.getDataId());
                                updateList.add(history);
                            } else if (retainDataIds.contains(history.getDataId())) {
                                // 更新的记录
                                Long aiAssistantId = history.getAiAssistantId();
                                if (smartMap.containsKey(aiAssistantId)) {
                                    AiAssistantEntity aiAssistantEntity = smartMap.get(aiAssistantId);
                                    JSONObject strategy = aiAssistantEntity.getStrategy();
                                    Integer strategyNum = strategy.getInteger("strategyNum") == null ? 0 : strategy.getInteger("strategyNum");
                                    if (history.getTriggerNum() >= strategyNum) {
                                        // 智能助手执行次数大于等于记录次数时，不在执行
                                        continue;
                                    }
                                }
                                updateList.add(history);
                                updateIds.add(history.getDataId());
                            } else {
                                // 待处理的数据
                                waitInvalidList.add(history);
                                waitInvalidIds.add(history.getDataId());
                            }
                        }
//                        else {
//                            // 执行动作改变：记录失效
//                            invalidIdsList.add(history.getId());
//                        }

                    }

                    // 添加数据
                    AiAssistantEntity entity = smartMap.get(smartId);
                    List<AiAssistantHistoryEntity> addList = getAddHistoryList(dataIds, entity);

                    // 需要添加和更新的数据ids
                    List<Long> addAndUpdateIds = new ArrayList<>(dataIds);
                    addAndUpdateIds.addAll(updateIds);

                    // 生成pojo
                    SsHistoryValidPojo pojo = new SsHistoryValidPojo();
                    pojo.setSmartSettingsId(smartId);
                    pojo.setAddList(addList);
                    pojo.setUpdateList(updateList);
                    pojo.setInvalidIdsList(invalidIdsList);
                    pojo.setAddAndUpdateIds(addAndUpdateIds);
                    pojo.setWaitInvalidList(waitInvalidList);
                    pojo.setWaitInvalidIds(waitInvalidIds);
                    validPojoList.add(pojo);

                    if (!waitInvalidIds.isEmpty()) {
                        waitInvalidIdsMap.put(smartId, waitInvalidIds);
                        waitInvalidListMap.put(smartId, waitInvalidList);
                    }
                }
            }
            aiAssistantHistoryPojo.setValidPojoList(validPojoList);
            aiAssistantHistoryPojo.setWaitInvalidListMap(waitInvalidListMap);
            aiAssistantHistoryPojo.setWaitInvalidIdsMap(waitInvalidIdsMap);
        } catch (Exception e) {
            LOGGER.error("获取执行次数出错：", e);
        }
        return aiAssistantHistoryPojo;
    }

    @Override
    public void handleWaitInvalidHistory(List<SsHistoryValidPojo> list, Map<Long, List<Long>> dataIdsMap) {
        for(SsHistoryValidPojo validPojo : list) {
            Long smartId = validPojo.getSmartSettingsId();
            List<Long> dataIds = dataIdsMap.get(smartId);

            // 待失效数据
            List<AiAssistantHistoryEntity> waitInvalidList = validPojo.getWaitInvalidList();
            if(waitInvalidList.isEmpty()) {
                continue;
            }
            // 没有有效数据，待失效的数据全部失效
            if(Objects.isNull(dataIds) || dataIds.isEmpty()) {
                List<Long> invalidIds = validPojo.getInvalidIdsList();
                invalidIds.addAll(validPojo.getWaitInvalidIds());
                validPojo.setInvalidIdsList(invalidIds);
                // 清空待失效的数据
                validPojo.setWaitInvalidIds(new ArrayList<>());
                validPojo.setWaitInvalidList(new ArrayList<>());
                continue;
            }

            for(AiAssistantHistoryEntity entity : waitInvalidList) {
                // 更新的数据
                if(dataIds.contains(entity.getDataId())) {
                    // 更新的数据
                    List<AiAssistantHistoryEntity> updateList = validPojo.getUpdateList();
                    updateList.add(entity);
                    validPojo.setUpdateList(updateList);
                    // 更新的数据ids
                    List<Long> addAndUpdateIds = validPojo.getAddAndUpdateIds();
                    addAndUpdateIds.add(entity.getDataId());
                    validPojo.setAddAndUpdateIds(addAndUpdateIds);
                }
            }
        }
    }

    /**
     * 新添加的有效记录
     *
     * @param dataIdsMap {smartId: [dataId1,dataId2]}
     * @param smartMap {smartId: smartEntity}
     * @return
     * @throws
     * @author hongxiao
     * @date 2019-08-24 14:02
     * @since v1.0
     * @version v1.0
     */
    private List<SsHistoryValidPojo> addValidList(Map<Long, List<Long>> dataIdsMap, Map<Long, AiAssistantEntity> smartMap) {
        List<SsHistoryValidPojo> resultList = new ArrayList<>();
        if(dataIdsMap.isEmpty()) {
            return resultList;
        }

        dataIdsMap.forEach((smartId, dataIds) -> {
            AiAssistantEntity entity = smartMap.get(smartId);
            SsHistoryValidPojo pojo = new SsHistoryValidPojo();
            pojo.setSmartSettingsId(smartId);
            pojo.setAddList(getAddHistoryList(dataIds, entity));
            pojo.setAddAndUpdateIds(dataIds);
            resultList.add(pojo);
        });

        return resultList;
    }

    /**
     * 获取有效的历史记录
     *
     * @param rabbitMqDTO 入参
     * @return
     * @throws
     * @author hongxiao
     * @date: 2019-05-11 11:11
     * @since v1.0
     * @version v1.0
     */
    private void getValidHistoryList(SmartStrategyRabbitMqDTO rabbitMqDTO, Map<Long, List<AiAssistantHistoryEntity>> historyList, Map<Long, List<AiAssistantHistoryEntity>> workReportHistoryList) {

        List<Long> aiAssistantIdIn = new ArrayList<>();
        // 工作报告不用判断，直接有效
        List<Long> workReportAssistantIdIn = new ArrayList<>();
        rabbitMqDTO.getList().forEach(item -> {
            aiAssistantIdIn.add(item.getId());
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), item.getSaasMark()) && Objects.equals(XbbRefTypeEnum.WORK_REPORT.getCode(), item.getBusinessType())) {
                workReportAssistantIdIn.add(item.getId());
            }
        });

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", rabbitMqDTO.getCorpid());
        param.put("aiAssistantIdIn", aiAssistantIdIn);
        param.put("del", DelEnum.NORMAL.getDel());
//        param.put("triggerInvalid", 0);
        int count = aiAssistantHistoryModel.getEntitysCount(param);
        long start = 0;
        int pageNum = 1000;
        if(count == 0) {
            return;
        }
        int index = count/pageNum + 1;
        for (int i = 0; i < index; i++) {
            param.put("idGte", start);
            param.put("pageSize", pageNum);
            List<AiAssistantHistoryEntity> list = aiAssistantHistoryModel.findEntitys(param);
            if(Objects.isNull(list) || list.isEmpty()) {
                return;
            }

            for(AiAssistantHistoryEntity historyEntity : list) {
                Long ssId = historyEntity.getAiAssistantId();
                start = historyEntity.getId();
                // 工作报告
                if (workReportAssistantIdIn.contains(ssId)) {
                    if (workReportHistoryList.containsKey(ssId)) {
                        workReportHistoryList.get(ssId).add(historyEntity);
                    } else {
                        List<AiAssistantHistoryEntity> subList = new ArrayList<>();
                        subList.add(historyEntity);
                        workReportHistoryList.put(ssId, subList);
                    }
                } else {
                    // 其他业务
                    if (historyList.containsKey(ssId)) {
                        historyList.get(ssId).add(historyEntity);
                    } else {
                        List<AiAssistantHistoryEntity> subList = new ArrayList<>();
                        subList.add(historyEntity);
                        historyList.put(ssId, subList);
                    }
                }
            }
        }
    }

    /**
     * 获取需要添加的记录列表
     *
     * @param dataIds 数据ids
     * @param aiAssistantEntity 智能助手实体
     * @return
     * @throws
     * @author hongxiao
     * @date: 2019-05-11 11:10
     * @since v1.0
     * @version v1.0
     */
    @Override
    public List<AiAssistantHistoryEntity> getAddHistoryList(List<Long> dataIds, AiAssistantEntity aiAssistantEntity) {
        if (dataIds.isEmpty()) {
            return new ArrayList<>();
        }
        List<AiAssistantHistoryEntity> list = new ArrayList<>();
        dataIds.forEach(dataId -> {
            AiAssistantHistoryEntity historyEntity = new AiAssistantHistoryEntity();
            BeanUtil.copyProperties(aiAssistantEntity, historyEntity);
            historyEntity.setId(null);
            historyEntity.setDataId(dataId);
            historyEntity.setAiAssistantId(aiAssistantEntity.getId());
            list.add(historyEntity);
        });
        return list;
    }
}
